import cPickle
from errors import *
from itertools import izip
[docs]class OffenseRules(object):
def __init__(self, log):
self.missing_codes = [9999, 999, 9, 9, 9, 99, 9]
self.unknown_codes = [9999, 999, 9, 9, 9, 99, 9]
self.not_coded = [-9999, -999, -9, -9, -9, -99, -9]
self.default_pred_codes = [9999, 999, 9, 9, 9, 99, 9]
self.vars = ['ncic', 'chg', 'inc', 'dom', 'weap', 'cdv', 'pg']
self.log = log
self.missing_map = zip(self.vars, self.missing_codes)
self.missing_dict = dict([[var, missing] for var, missing in self.missing_map])
self.unknown_map = zip(self.vars, self.unknown_codes)
self.unknown_dict = dict([[var, unknown] for var, unknown in self.unknown_map])
self.not_coded_map = zip(self.vars, self.unknown_codes)
self.not_coded_dict = dict([[var, unknown] for var, unknown in self.unknown_map])
[docs] def convert_inc(self, row, vars, ruleset, log_name):
key = '|'.join(ruleset.metadata.get_key(row))
if vars['inc'] is None:
if key:
try:
if ruleset:
return ruleset.convert(key)
else:
#if no crosswalk defined than any value other than missing is logged
self.log.write(log_name, [row['id'], row['rapstatex'], key,
"New value for key (%s)" % '|'.join([k.name for k in ruleset.metadata.key_meta])])
except ConvertError:
self.log.write(log_name, [row['id'], row['rapstatex'], key,
"New value for key (%s)" % '|'.join([k.name for k in ruleset.metadata.key_meta])])
return self.unknown_dict['inc']
else:
return self.missing_dict['inc']
else:
return vars['inc']
def _convert_offenses(self, key, crosswalk, skip_coding = []):
convert_key = '|'.join(key)
missing_key = True
temp_vars = {}
for x in key:
#if one of the values in the key is Not None than missing_key set to false and we break the loop
if x:
missing_key = False
break
if missing_key:
#assign missing values when all variables in the key are None
for k, v in self.missing_map:
if k not in skip_coding:
temp_vars[k] = v
else:
temp_vars[k] = None
else:
for k, v in izip(self.vars, crosswalk.convert(convert_key, split='|')):
temp_vars[k] = v
return temp_vars
[docs] def convert_offenses(self, row, rulesets, rule_order, _index=0, full_key=None, ground_truth={}):
"""
@param rules: The crosswalk object containing all the RuleSets.
@param rule_order: A list of tuples (x,y) where x = key to locate in RuleSet and y = name of RuleSet.
Length of list determines depth of recursion.
@param skip_missing_coding: A list containing the names of offense variables to not code
as missing if no match is found in crosswalk.
"""
#TODO remove "recursion" because not really recursion
vars = {}
ruleset = rulesets[rule_order[_index]]
if 'remove' in rule_order[_index]:
#if a remove crosswalk is detected apply the delete_transform
_key = ruleset.delete_transform(ruleset.metadata.get_key(row, as_str=True))
_row = dict([(ruleset.metadata.key_meta[i].name, k) for i,k in enumerate(_key.split('|'))])
#then use the transformed key in the next ruleset
_index += 1
ruleset = rulesets[rule_order[_index]]
for key_meta in ruleset.metadata.key_meta:
#add any new key variables to the _row object
if key_meta.name not in _row:
_row[key_meta.name] = row[key_meta.name]
key = ruleset.metadata.get_key(_row)
else:
key = ruleset.metadata.get_key(row)
if not full_key:
full_key = (ruleset.metadata.keys.keys(), ruleset.metadata.keys.values())
else:
for k, v in ruleset.metadata.keys.iteritems():
if k not in full_key[0]:
full_key[0].append(k)
full_key[1].append(v)
index = _index + 1
try:
#code ancic, achg, ainc, adom, aweap, acdv, apg using key in ruleset
vars = self._convert_offenses(key, ruleset, skip_coding = ruleset.skip_missing)
except ConvertError:
#check to see if we need to recurse
if index == len(rule_order):
#output unknown values
for k, v in self.unknown_map:
vars[k] = None
#log no match using key and predictions
#TODO make full_key that contains all the key values for all the rulesets
self.log.write(self.log.var,
[row['id'], row['rapstatex'],
'|'.join([_k.name for _k in sorted(full_key[1], key= lambda k: k.order)]),
'|'.join([_k.get_key(row) for _k in sorted(full_key[1], key= lambda k: k.order)]),
"key not found in crosswalk_%s" % rule_order[_index][1]],
type=2)
else:
#dive down one layer
return self.convert_offenses(row, rulesets, rule_order, index, full_key, ground_truth)
return vars